use std::{time::Duration, fs::File, io::Read, thread};
use serde::{Serialize, Deserialize};
use snowflake::SnowflakeIdGenerator;

#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Eq)]
pub struct IpAddr {
    pub host: String,
    pub port: u16,
}

fn default_log() -> String {
    String::from("/var/log/nrgrid/nrgrid-cli.log")
}

fn default_id() -> i64 {
    let mut generator = SnowflakeIdGenerator::new(1, 3);
    generator.generate()
}

#[derive(Serialize, Deserialize, PartialEq, Debug, Eq, Clone)]
pub struct ConfCli {
    // 服务器地址
    pub remote: IpAddr,
    // 本地地址
    pub local: IpAddr,
    // 匹配规则 服务器设置 默认正则表达式
    pub rule: Vec<String>,
    #[serde(default = "default_log")]
    pub log: String,
    #[serde(default = "default_id")]
    pub id: i64,
}

impl ConfCli {
    pub fn get_conf() -> ConfCli {
        loop {
            match Self::read_conf() {
                Some(conf) => {
                    return conf;
                },
                None => {
                    println!("Undefind cli config");
                    thread::sleep(Duration::from_secs(1));
                },
            }
        }
    }

    fn read_conf() -> Option<ConfCli> {
        let lock = super::CLI_CONF.read().unwrap();
        let conf = &*lock;
        match conf {
            Some(a) => {
                Option::Some(a.clone())
            },
            None => {
                Option::None
            },
        }
    }

    pub fn load_conf() -> bool {
        let mut change = false;
        let mut conf_file = File::open("./conf/cli.yml").unwrap();
        let mut conf_str = String::new();
        conf_file.read_to_string(&mut conf_str).unwrap();
        let mut conf: ConfCli = serde_yaml::from_str(&conf_str).unwrap();
        let mut lock = super::CLI_CONF.write().unwrap();
        match &*lock {
            Some(temp) => {
                conf.id = temp.id;
                if !conf.eq(temp) {
                    change = true;
                }
            },
            None => {
                change = true;
            },
        }
        if change {
            println!("Update cli config");
            *lock = Option::Some(conf);
        }
        change
    }
}

#[derive(Debug, Clone)]
pub enum Health {
    HIGH,
    // LOW,
    // DOWN,
}

// 服务端保存的客户端信息
#[derive(Debug, Clone)]
pub struct ConfCliPlus {
    // 终端信息
    pub cli: ConfCli,
    // 终端健康状态
    pub health: Health,
    // update: SystemTime,
}

impl ConfCliPlus {
    pub fn new(cli: ConfCli) -> Self {
        Self {
            cli,
            health: Health::HIGH,
            // update: SystemTime::now()
        }
    }

    // pub fn check_health(&mut self) {
    //     let duration = SystemTime::now().duration_since(self.update).unwrap();
    //     if duration.as_secs() > 300 {
    //         self.health = Health::DOWN
    //     } else if duration.as_secs() > 60 {
    //         self.health = Health::LOW
    //     } else {
    //         self.health = Health::HIGH
    //     }
    // }

    // pub fn update(&mut self) {
    //     self.update = SystemTime::now();
    // }

}